﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ParserGenerator.CharacterMapping;
using ParserGenerator.SyntacticAnalysis;

namespace ParserGenerator.ScannerConstruction
{
    [Serializable]
    public sealed class ScannerAutomatonItemTable : ReadOnlyCollection<ScannerAutomatonItem>
    {
        internal ScannerAutomatonItemTable()
            : base(new List<ScannerAutomatonItem>())
        {
        }

        internal ScannerAutomatonItem DefineShift(CharClass symbol)
        {
            if (symbol == null)
                throw new ArgumentNullException(nameof(symbol));
            var item = new ScannerAutomatonShift(Items.Count, symbol);
            Items.Add(item);
            return item;
        }

        internal ScannerAutomatonItem DefineReduction(LexicalRuleDeclarator rule)
        {
            if (rule == null)
                throw new ArgumentNullException(nameof(rule));
            var item = new ScannerAutomatonReduction(Items.Count, rule);
            Items.Add(item);
            return item;
        }

        internal void UpdateFollowSet(ScannerAutomatonItemSet x, ScannerAutomatonItemSet y)
        {
            if (x == null)
                throw new ArgumentNullException(nameof(x));
            if (y == null)
                throw new ArgumentNullException(nameof(y));
            foreach (ScannerAutomatonItem p in x)
                p.FollowSet.UnionWith(y);
        }

        internal void UpdateFollowSet(ScannerAutomatonItemSet x, ScannerAutomatonItem y)
        {
            if (x == null)
                throw new ArgumentNullException(nameof(x));
            if (y == null)
                throw new ArgumentNullException(nameof(y));
            foreach (ScannerAutomatonItem p in x)
                p.FollowSet.Add(y);
        }

        public sealed override string ToString()
        {
            return string.Join("\n", Items);
        }
    }
}
